<?php
/**
* Handle pingbacks to any page handled by the CMS.
*
* Every front-end page rendered by Scribble will include the "X-Pingback" HTTP
* header which lets external resources know the correct pingback URL.
*
* Copyright (c) 2009 James Gauld <james@jamesgauld.net>
* This file is part of Scribble.
* @license http://www.scribblecms.co.uk/license.txt
*
* @link http://www.hixie.ch/specs/pingback/pingback Pingback spec
* @package Scribble
*/
use Buan\ExtensionManager;
class PingbackController extends ScribblePublicController {

	/**
	* Accept a ping request, store it in the database for future use and send back
	* a ping response.
	*
	* No View is returned by the method as it will simply exit with a plain text
	* response.
	*
	* @param array Action parameters (none supported)
	* @return void
	*/
	public function index($params) {

		// Prepare response
		$response = new StdClass();
		$response->faultCode = NULL;
		$response->faultString = '';
		$response->returnValue = '';

		// Gather XML RPC request
		$rawRequest = file_get_contents("php://input");
		if(!empty($rawRequest)) {

			// Load XML and validate structure
			$request = simplexml_load_string($rawRequest);
			$params = isset($request->params) ? (array)$request->params->children() : array('param'=>array());
			$params = $params['param'];
			if(!isset($request->methodName) || $request->methodName!='pingback.ping') {
				$response->faultCode = 0;
				$response->faultString = 'Invalid XML RPC methodName.';
			}
			else if(count($params)<2) {
				$response->faultCode = 0;
				$response->faultString = 'Argument count mismatch.';
			}

			// Find target page on this server
			else {
				$targetUri = (string)$request->params->param[1]->value->string;
				$page = PageManager::loadByUrlCommand(SiteManager::getCurrentSite(), $targetUri);
				if($page===NULL) {
					$response->faultCode = 32;
					$response->faultString = 'The specified target URI does not exist.';
				}

				// Save ping
				else {
					$ping = Model::create('Ping');
					$ping->addRelatedModel($page);
					$ping->httprequest = $rawRequest;
					if(!$ping->getModelManager()->save($ping)) {
						$response->faultCode = 0;
						$response->faultString = 'Failed to create ping.';
					}
					else {
						$response->returnValue = 'Ping created successfully.';
					}
				}
			}
		}
		else {
			$response->faultCode = 0;
			$response->faultString = 'Incorrectly formatted XML RPC request.';
		}

		// Write response
		session_write_close();
		header("Content-Type: text/xml");
		if($response->faultCode!==NULL) {
			$response = "<methodResponse><fault><value><struct><member><name>faultCode</name><value><int>{$response->faultCode}</int></value></member><member><name>faultString</name><value><string>{$response->faultString}</string></value></member></struct></value></fault></methodResponse>";
		}
		else {
			$response = "<methodResponse><params><param><value><string>{$response->returnValue}</string></value></param></params></methodResponse>";
		}
		$response = "<"."?xml version=\"1.0\"?".">\n".$response;
		header("Content-Length: ".strlen($response));
		die($response);
	}
}
?>